import { useVisible } from "./VisibleProvider";
import style from "./Dialog.module.css";
import { FormEvent, KeyboardEvent, useEffect, useRef, useState } from "react";
import { RadioGroup } from "./components/RadioGroup";
import CloseIcon from "src/assets/icons/close.svg";
import SendIcon from "src/assets/icons/send.svg";
import Messages from "src/components/Message/Messages";
import { search } from "./api";
import parseReadableStream from "./utils/parseReadableStream";

const radioOptions = [
  {
    label: "总结",
    value: 0,
  },
  {
    label: "CBDB",
    value: 1,
  },
  {
    label: "四库全书",
    value: 2,
  },
];

export default function Dialog() {
  const {
    isDialogVisible: visible,
    toggleButtonVisible,
    toggleDialogVisible,
  } = useVisible();
  const [type, setType] = useState(0);
  const [input, setInput] = useState("");
  const [messages, setMessages] = useState<
    (UserMessageInterface | AssistantMessageInterface)[]
  >([]);
  const responseMessageIdRef = useRef<string>();
  const cancelCompletionRef = useRef<AbortController | null>(null);

  function closeDialog() {
    toggleButtonVisible(true);
    toggleDialogVisible(false);
  }

  function handleSubmit(e?: FormEvent) {
    e?.preventDefault();
    if (input.trim() === "") {
      return;
    }
    if (responseMessageIdRef.current) {
      console.log(responseMessageIdRef.current);
      return;
    }
    setInput("");
    console.log("submit", input);
    setMessages([
      ...messages,
      { role: "user", content: input },
      generateNewResponseMessage(),
    ]);
    handleCompletion(type, input);
  }

  function handleKeyDown(e: KeyboardEvent) {
    const { key, shiftKey } = e;
    if (key === "Enter" && !shiftKey) {
      e.preventDefault();
      handleSubmit();
    }
  }

  async function handleCompletion(type: number, query?: string) {
    // query_str -- 对应接口“query”字段
    // query_result -- 对应接口 “keyword_result”字段
    // person_list -- 对应接口 “graph_keyword”字段
    const _query = query || window.query_str;
    const keyword_result = window.query_result;
    const graph_keyword = window.person_list;
    const controller = new AbortController();
    cancelCompletionRef.current = controller;
    const response = await search({
      query: _query,
      graph_keyword,
      keyword_result,
      type,
      signal: controller.signal,
    });
    if (!response) {
      // 网络错误
    } else if (!response.ok) {
      // 服务器返回错误
    } else {
      parseReadableStream(response.body!, {
        onProgress: function (data) {
          // graph retrieval summary recommend
          console.log(data.type, data);
          const responseMessageId = responseMessageIdRef.current;
          setMessages((messages) => {
            const assistantMessage = messages.find(
              (message) =>
                message.role === "assistant" && message.id === responseMessageId
            ) as AssistantMessageInterface;
            const message = Object.assign({}, assistantMessage);
            if (data.type === "graph") {
              message.graph = data.data;
            } else if (data.type === "retrieval") {
              message.retrieval = data.data;
            } else if (data.type === "summary") {
              message.content = data.data;
            } else if (data.type === "recommend") {
              message.recommend = data.data;
            }
            return messages.map((m) =>
              m.role === "assistant" && m.id === responseMessageId ? message : m
            );
          });
        },
      })
        .then(() => {
          console.log("finish");
          const responseMessageId = responseMessageIdRef.current;
          responseMessageIdRef.current = undefined;
          setMessages((messages) => {
            const assistantMessage = messages.find(
              (message) =>
                message.role === "assistant" && message.id === responseMessageId
            ) as AssistantMessageInterface;
            let message = Object.assign({}, assistantMessage, { done: true });

            return messages.map((m) =>
              m.role === "assistant" && m.id === responseMessageId ? message : m
            );
          });
        })
        .catch((err) => {
          console.log(err);
        });
    }
  }

  function generateNewResponseMessage() {
    responseMessageIdRef.current = Date.now().toString(16);
    return {
      id: responseMessageIdRef.current,
      role: "assistant",
      content: "",
      graph: [],
      retrieval: [],
      recommend: [],
      done: false,
    } as AssistantMessageInterface;
  }

  useEffect(() => {
    if (visible) {
      setMessages([generateNewResponseMessage()]);
      handleCompletion(type);
    }
    return () => {
      cancelCompletionRef.current?.abort("CancelReauest");
    };
  }, [visible, type]);

  if (!visible) return null;

  return (
    <div className={style.dialog}>
      <button className={style.close} onClick={closeDialog}>
        <CloseIcon height={24} width={24} />
      </button>
      <div className={style.header}>
        <RadioGroup
          options={radioOptions}
          value={type}
          name="type"
          onChange={setType}
        />
      </div>
      <div className={style.content}>
        <Messages messages={messages} />
      </div>
      <div className={style.footer}>
        <form onSubmit={handleSubmit}>
          <textarea
            rows={4}
            className={style.textarea}
            value={input}
            onInput={(e) => setInput((e.target as HTMLTextAreaElement).value)}
            placeholder="请输入"
            onKeyDown={handleKeyDown}
          ></textarea>
          <button type="submit" className={style.send}>
            <SendIcon />
          </button>
        </form>
      </div>
    </div>
  );
}
